package com.virtualparadigm.hierarchy;

import java.io.Serializable;
import java.util.Iterator;
import java.util.LinkedList;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public class LineageList<T> implements Serializable, Cloneable
{
	private static final long serialVersionUID = 1L;
	private LinkedList<T> lList;
	
	public LineageList()
	{
		this.lList = new LinkedList<T>();
	}
	
	public void pushParent(T t)
	{
		this.lList.addFirst(t);
	}
	public T popParent()
	{
		return this.lList.removeFirst();
	}
	public T peekParent()
	{
		return this.lList.getFirst();
	}
	
	public void queueChild(T t)
	{
		this.lList.addLast(t);
	}
	public T dequeueChild()
	{
		return this.lList.removeLast();
	}
	public T peekChild()
	{
		return this.lList.getLast();
	}
	
	public Iterator<T> getParentsFirstIterator()
	{
		return this.lList.iterator();
	}
	
	public Iterator<T> getChildrenFirstIterator()
	{
		return this.lList.descendingIterator();
	}
	
	public int getSize()
	{
		return this.lList.size();
	}
	
	private LinkedList<T> getLList()
	{
		return this.lList;
	}


	// ================================================
	// UTILITY METHODS
	// ================================================
	public int hashCode()
	{
		HashCodeBuilder builder = new HashCodeBuilder(17,31);
	    builder.append(this.getLList());
	    return builder.toHashCode();		
	}
	
	public boolean equals(Object obj)
	{
		if (obj == null)
		{
			return false;
		}
		if (obj == this)
		{
			return true;
		}
		if (obj.getClass() != getClass())
		{
			return false;
		}
		LineageList<T> that = (LineageList<T>)obj;
		EqualsBuilder builder = new EqualsBuilder();
	    builder.append(this.getLList(), that.getLList());
		return builder.isEquals();
	}
	
	public String toString()
	{
		return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
	}
	
	@Override
	public Object clone() throws CloneNotSupportedException
	{
		LineageList<T> cloned = (LineageList<T>)super.clone();
		cloned.lList = new LinkedList<T>();
		for(Iterator<T> it=this.getParentsFirstIterator(); it.hasNext(); )
		{
			cloned.queueChild(it.next());
		}
		return cloned;
	}
	
	public static void main(String[] args)
	{
		LineageList<String> ll = new LineageList<String>();
		ll.pushParent("p1");
		ll.pushParent("p2");
		ll.pushParent("p3");
		System.out.println(ll.toString());
	}
	
}